package com.xiaohua.api.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xiaohua.api.domain.XhApiFile;
import com.xiaohua.api.mapper.XhApiFileMapper;
import com.xiaohua.api.service.IOperationLogService;
import com.xiaohua.api.service.IXhFileService;
import com.xiaohua.common.core.domain.AjaxResult;
import com.xiaohua.common.utils.StringUtils;

/**
 * API文件服务实现类
 * 
 * @author 小花
 * @date 2025-04-07
 */
@Service
public class XhFileServiceImpl implements IXhFileService {
    
    private static final Logger log = LoggerFactory.getLogger(XhFileServiceImpl.class);
    
    @Autowired
    private XhApiFileMapper xhApiFileMapper;
    
    @Autowired
    private IOperationLogService operationLogService;
    
    // 使用ThreadLocal记录当前操作是否已经记录日志，避免重复记录
    private static final ThreadLocal<Boolean> operationLogged = ThreadLocal.withInitial(() -> false);
    
    @Override
    public Long saveFile(Long userId, String fileName, String fileType, String storagePath, 
            Integer isEncrypted, String encryptionKey) {
        try {
            // 创建文件信息对象
            XhApiFile xhFile = XhApiFile.builder()
                .userId(userId)
                .fileName(fileName)
                .fileType(fileType)
                .storagePath(storagePath)
                .isEncrypted(isEncrypted)
                .encryptionKey(encryptionKey)
                .createdAt(new Date())
                .build();
            
            // 插入数据库
            xhApiFileMapper.insertFile(xhFile);
            
            // 返回自动生成的主键
            return xhFile.getFileId();
        } catch (Exception e) {
            log.error("保存文件信息到数据库失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    @Override
    public Long saveFile(Long userId, File file, String storagePath, Integer isEncrypted) {
        if (file == null || !file.exists()) {
            log.error("文件不存在");
            return null;
        }
        
        try {
            String fileName = file.getName();
            String fileType = FilenameUtils.getExtension(fileName);
            
            return saveFile(userId, fileName, fileType, storagePath, isEncrypted, null);
        } catch (Exception e) {
            log.error("保存文件信息到数据库失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    @Override
    public boolean saveFileFromResult(Long userId, AjaxResult result, String operationType) {
        // 重置操作日志标志
        operationLogged.set(false);
        
        if (result == null || !result.isSuccess()) {
            log.error("操作结果为空或操作失败");
            return false;
        }
        
        try {
            // 使用AtomicBoolean跟踪是否保存了任何文件
            AtomicBoolean savedAnyFile = new AtomicBoolean(false);
            
            // 1. 首先尝试从url字段获取文件路径
            String url = (String) result.get("url");
            if (StringUtils.isNotEmpty(url)) {
                processUrlAndSaveFile(userId, url, operationType, savedAnyFile);
            } else {
                // 2. 尝试获取多个文件URL的情况
                Object urlsObject = result.get("urls");
                if (urlsObject instanceof List) {
                    processUrlListAndSaveFiles(userId, (List<String>) urlsObject, operationType, savedAnyFile);
                }
                
                // 3. 如果还没有保存任何文件，尝试获取data字段中的信息
                if (!savedAnyFile.get()) {
                    Object dataObj = result.get("data");
                    if (dataObj instanceof Map) {
                        processDataMapAndSaveFile(userId, (Map<String, Object>) dataObj, operationType, savedAnyFile);
                    }
                }
            }
            
            // 清除ThreadLocal变量，避免内存泄漏
            operationLogged.remove();
            
            return savedAnyFile.get();
        } catch (Exception e) {
            log.error("从AjaxResult提取文件信息失败: {}", e.getMessage(), e);
            // 清除ThreadLocal变量，避免内存泄漏
            operationLogged.remove();
            return false;
        }
    }
    
    /**
     * 处理单个URL并保存文件信息
     */
    private void processUrlAndSaveFile(Long userId, String url, String operationType, AtomicBoolean savedAnyFile) {
        // 提取文件名，默认使用URL的最后一部分作为文件名
        String fileName = extractFileName(url);
        String fileType = FilenameUtils.getExtension(fileName);
        
        // 获取是否加密信息，如果没有则默认为未加密(0)
        Integer isEncrypted = 0;
        
        // 如果操作类型包含"加密"，则标记为已加密
        if (operationType != null && operationType.contains("加密")) {
            isEncrypted = 1;
        }
        
        // 保存文件信息
        Long fileId = saveFile(userId, fileName, fileType, url, isEncrypted, null);
        
        // 记录操作日志
        if (fileId != null && !operationLogged.get()) {
            operationLogService.logOperation(userId, fileId, operationType, 200);
            operationLogged.set(true);
            savedAnyFile.set(true);
        }
    }
    
    /**
     * 处理URL列表并保存多个文件信息
     */
    private void processUrlListAndSaveFiles(Long userId, List<String> urls, String operationType, AtomicBoolean savedAnyFile) {
        List<Long> fileIds = new ArrayList<>();
        
        for (String fileUrl : urls) {
            String fileName = extractFileName(fileUrl);
            String fileType = FilenameUtils.getExtension(fileName);
            
            // 获取是否加密信息，如果没有则默认为未加密(0)
            Integer isEncrypted = 0;
            
            // 如果操作类型包含"加密"，则标记为已加密
            if (operationType != null && operationType.contains("加密")) {
                isEncrypted = 1;
            }
            
            // 保存文件信息
            Long fileId = saveFile(userId, fileName, fileType, fileUrl, isEncrypted, null);
            if (fileId != null) {
                fileIds.add(fileId);
            }
        }
        
        // 记录操作日志
        if (!fileIds.isEmpty() && !operationLogged.get()) {
            operationLogService.logOperationWithMultipleFiles(userId, fileIds, operationType, 200);
            operationLogged.set(true);
            savedAnyFile.set(true);
        }
    }
    
    /**
     * 处理数据Map中的URL并保存文件信息
     */
    private void processDataMapAndSaveFile(Long userId, Map<String, Object> dataMap, String operationType, AtomicBoolean savedAnyFile) {
        // 优先获取url字段
        String dataUrl = (String) dataMap.get("url");
        if (StringUtils.isNotEmpty(dataUrl)) {
            String fileName = extractFileName(dataUrl);
            String fileType = FilenameUtils.getExtension(fileName);
            
            // 判断是否加密
            Integer isEncrypted = 0;
            if (operationType != null && operationType.contains("加密")) {
                isEncrypted = 1;
            }
            
            // 保存并记录
            Long fileId = saveFile(userId, fileName, fileType, dataUrl, isEncrypted, null);
            if (fileId != null && !operationLogged.get()) {
                operationLogService.logOperation(userId, fileId, operationType, 200);
                operationLogged.set(true);
                savedAnyFile.set(true);
            }
        }
    }
    
    /**
     * 从URL中提取文件名
     * 
     * @param url 文件URL
     * @return 文件名
     */
    private String extractFileName(String url) {
        if (StringUtils.isEmpty(url)) {
            return "unknown";
        }
        
        // 移除URL参数
        String cleanUrl = url;
        int queryParamIndex = url.indexOf('?');
        if (queryParamIndex > 0) {
            cleanUrl = url.substring(0, queryParamIndex);
        }
        
        // 获取最后一个/后的内容作为文件名
        int lastSlashIndex = cleanUrl.lastIndexOf('/');
        if (lastSlashIndex >= 0 && lastSlashIndex < cleanUrl.length() - 1) {
            return cleanUrl.substring(lastSlashIndex + 1);
        }
        
        return "file_" + System.currentTimeMillis();
    }
} 